/*
 * LiquidBounce Hacked Client
 * A free open source mixin-based injection hacked client for Minecraft using Minecraft Forge.
 * https://github.com/CCBlueX/LiquidBounce/
 */
package zelix.hack.hacks;


import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.network.play.client.CPacketPlayer;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.RayTraceResult;
import net.minecraftforge.fml.common.gameevent.TickEvent;
import org.lwjgl.input.Mouse;
import org.lwjgl.util.vector.Vector3f;
import zelix.hack.Hack;
import zelix.hack.HackCategory;
import zelix.utils.BlockUtils;
import zelix.utils.PlayerUtil;
import zelix.utils.hooks.visual.ChatUtils;
import zelix.value.BooleanValue;
import zelix.value.Mode;
import zelix.value.ModeValue;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;


public class ItemTeleport extends Hack {


    public Minecraft mc = Minecraft.getMinecraft();
    private final ModeValue mode;
    private final BooleanValue resetAfterTp = new BooleanValue("ResetAfterTP", true);
    private final ModeValue button;

    private int delay;
    private BlockPos endPos;
    private RayTraceResult objectPosition;

    public ItemTeleport() {
        super("ItemTeleport", HackCategory.PLAYER);
        this.mode = new ModeValue("Mode", new Mode("New", true), new Mode("Old", false));
        this.button = new ModeValue("Button", new Mode("Left", false), new Mode("Right", false), new Mode("Middle", true));
        this.addValue(mode, button, resetAfterTp);
    }


    @Override
    public void onDisable() {
        delay = 0;
        endPos = null;
        super.onDisable();
    }

    @Override
    public void onClientTick(TickEvent.ClientTickEvent event) {
        if (Mouse.isButtonDown(Arrays.asList(button.getModes()).indexOf(button.getSelectMode())) && delay <= 0) {
            objectPosition = mc.objectMouseOver;
            endPos = objectPosition.getBlockPos();

            IBlockState state = BlockUtils.getState(endPos);

            if (state.getBlock().getMaterial(state) == Material.AIR) {
                endPos = null;
                return;
            }

            ChatUtils.message("§7[§8§lItemTeleport§7] §3Position was set to §8" + endPos.getX() + "§3, §8" + endPos.getY() + "§3, §8" + endPos.getZ());
            delay = 6;
        }

        if (delay > 0)
            --delay;

        EntityPlayerSP thePlayer = mc.player;

        if (thePlayer == null)
            return;

        if (endPos != null && thePlayer.isSneaking()) {
            if (!thePlayer.onGround) {
                final double endX = (double) endPos.getX() + 0.5D;
                final double endY = (double) endPos.getY() + 1D;
                final double endZ = (double) endPos.getZ() + 0.5D;

                switch (mode.getSelectMode().getName().toLowerCase()) {
                    case "old":
                        for (final Vector3f vector3f : vanillaTeleportPositions(endX, endY, endZ, 4D))
                            mc.getConnection().sendPacket(new CPacketPlayer.Position(vector3f.getX(), vector3f.getY(), vector3f.getZ(), false));
                        break;
                    case "new":
                        for (final Vector3f vector3f : vanillaTeleportPositions(endX, endY, endZ, 5D)) {
                            mc.getConnection().sendPacket(new CPacketPlayer.Position(thePlayer.posX, thePlayer.posY, thePlayer.posZ, true));
                            mc.getConnection().sendPacket(new CPacketPlayer.Position(vector3f.x, vector3f.y, vector3f.z, true));
                            mc.getConnection().sendPacket(new CPacketPlayer.Position(thePlayer.posX, thePlayer.posY, thePlayer.posZ, true));
                            mc.getConnection().sendPacket(new CPacketPlayer.Position(thePlayer.posX, thePlayer.posY + 4.0, thePlayer.posZ, true));
                            mc.getConnection().sendPacket(new CPacketPlayer.Position(vector3f.x, vector3f.y, vector3f.z, true));
                           // MovementUtils.forward(0.04);
                            PlayerUtil.forward(0.04);
                        }
                        break;
                }

                if (resetAfterTp.getValue())
                    endPos = null;

                ChatUtils.message("§7[§8§lItemTeleport§7] §3Tried to collect items");
            } else
                thePlayer.jump();
        }
    }


    /*
    @Override
    public void onRenderWorldLast(RenderWorldLastEvent event) {
        objectPosition = mc.player.rayTrace(1000, event.getPartialTicks());

        if (objectPosition.getBlockPos() == null)
            return;

        final int x = objectPosition.getBlockPos().getX();
        final int y = objectPosition.getBlockPos().getY();
        final int z = objectPosition.getBlockPos().getZ();

        IBlockState state = BlockUtils.getState(objectPosition.getBlockPos());

        if (!state.getBlock().getMaterial(state).equals(Material.AIR)) {
            final RenderManager renderManager = mc.getRenderManager();

            glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
            glEnable(GL_BLEND);
            glLineWidth(2F);
            glDisable(GL_TEXTURE_2D);
            glDisable(GL_DEPTH_TEST);
            glDepthMask(false);

            IBlockState state1 = BlockUtils.getState(objectPosition.getBlockPos().up());

            RenderUtils.glColor(!state1.getBlock().getMaterial(state1).equals(Material.AIR) ? new Color(255, 0, 0, 90) : new Color(0, 255, 0, 90));
            RenderUtils.drawFilledBox(new AxisAlignedBB(x - renderManager.getRenderPosX(), (y + 1) - renderManager.getRenderPosY(), z - renderManager.getRenderPosZ(), x - renderManager.getRenderPosX() + 1D, y + 1.2D - renderManager.getRenderPosY(), z - renderManager.getRenderPosZ() + 1D));
            glEnable(GL_TEXTURE_2D);
            glEnable(GL_DEPTH_TEST);
            glDepthMask(true);
            glDisable(GL_BLEND);

            Core.fontLoaders.default30.drawString(mc.player.getDistance(x, y, z) + "m", x + 0.5, y + 1.7, new Color(255, 0, 0, 90).getRGB(),true);

            //Proflier.renderNameTag(Math.round(mc.player.getDistance(x, y, z)) + "m", x + 0.5, y + 1.7, z + 0.5);
            GlStateManager.resetColor();
        }
    }

     */

    private List<Vector3f> vanillaTeleportPositions(final double tpX, final double tpY, final double tpZ, final double speed) {
        final List<Vector3f> positions = new ArrayList<>();
        double posX = tpX - mc.player.posX;
        double posZ = tpZ - mc.player.posZ;
        float yaw = (float) ((Math.atan2(posZ, posX) * 180 / Math.PI) - 90F);
        double tmpX;
        double tmpY = mc.player.posY;
        double tmpZ;
        double steps = 1;

        for (double d = speed; d < getDistance(mc.player.posX, mc.player.posY, mc.player.posZ, tpX, tpY, tpZ); d += speed)
            steps++;

        for (double d = speed; d < getDistance(mc.player.posX, mc.player.posY, mc.player.posZ, tpX, tpY, tpZ); d += speed) {
            tmpX = mc.player.posX - (Math.sin(Math.toRadians(yaw)) * d);
            tmpZ = mc.player.posZ + Math.cos(Math.toRadians(yaw)) * d;
            tmpY -= (mc.player.posY - tpY) / steps;
            positions.add(new Vector3f((float) tmpX, (float) tmpY, (float) tmpZ));
        }

        positions.add(new Vector3f((float) tpX, (float) tpY, (float) tpZ));

        return positions;
    }

    private double getDistance(double x1, double y1, double z1, double x2, double y2, double z2) {
        double d0 = x1 - x2;
        double d1 = y1 - y2;
        double d2 = z1 - z2;
        return Math.sqrt(d0 * d0 + d1 * d1 + d2 * d2);
    }


}
